package com.liusuai.yixian.WebSocket;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.liusuai.yixian.login.UserBean;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.CopyOnWriteArraySet;

@ServerEndpoint(value = "/websocket/{userId}")
@Component
public class WebSocketControler {


    private WebSocketService webSocketService;

    //静态变量，用来记录当前在线连接数。应该把它设计成线程安全的。
    private static int onlineCount = 0;

    //concurrent包的线程安全Set，用来存放每个客户端对应的MyWebSocket对象。
    private static CopyOnWriteArraySet<WebSocketControler> webSocketSet = new CopyOnWriteArraySet<WebSocketControler>();

    //与某个客户端的连接会话，需要通过它来给客户端发送数据
    private Session session;

    //此处是解决无法注入的关键
    private static ApplicationContext applicationContext;
    //你要注入的service或者dao

    public static void setApplicationContext(ApplicationContext applicationContext) {
        WebSocketControler.applicationContext = applicationContext;
    }

    /**
     * 连接建立成功调用的方法
     */
    @OnOpen
    public void onOpen(@PathParam("userId") String userId, Session session) {
        this.session = session;

        webSocketService = applicationContext.getBean(WebSocketService.class);

        //更新user表的socket之前，先查查有没有在别的地方已经登录，如果已经登录，就先挤掉前边的。
        UserBean userOld = webSocketService.getUserByID(userId);
        Session sessionOld = getSessionById(userOld.getSocketId());
        if (sessionOld!=null){
            try {
                sessionOld.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        webSocketService.updateSocketId(session.getId(), userId);

        webSocketSet.add(this);     //加入set中
        addOnlineCount();           //在线数加1
        System.out.println("有新连接加入！当前在线人数为" + getOnlineCount());

        //查询是否有未接收的信息
        List<UnSendMsgBean> unGotMsgList = webSocketService.getUnGotMsg(userId);

        if (unGotMsgList != null && unGotMsgList.size() > 0) {
            for (UnSendMsgBean message : unGotMsgList) {
                String data = message.getData();
                JSONObject json = (JSONObject) JSON.parse(data);
                sendMessage(json.toJSONString());
            }
            webSocketService.delUnGotMsgS(userId);
        }

    }

    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose() {
        webSocketSet.remove(this);  //从set中删除
        subOnlineCount();           //在线数减1
        System.out.println("有一连接关闭！当前在线人数为" + getOnlineCount());

    }

    /**
     * 收到客户端消息后调用的方法
     *
     * @param message 客户端发送过来的消息
     */
    @OnMessage
    public void onMessage(String message, Session session) {
        System.out.println("来自客户端的消息:" + message);

        JSONObject jsonObject = (JSONObject) JSON.parse(message);


        String type = jsonObject.getString("type");
        String fromId = jsonObject.getString("fromId");
        JSONArray toIds = jsonObject.getJSONArray("toIds");
        String groupId = jsonObject.getString("groupId");
        JSONObject data = jsonObject.getJSONObject("data");

        UserBean fromUser = webSocketService.getUserByID(fromId);
        if (type.equals("0")) {
            //单独发给一个人

            UserBean toUser = webSocketService.getUserByID((String) toIds.get(0));
            sendMessageToUser(fromUser, toUser, type, "", data);

        } else if (type.equals("1") || type.equals("2")) {
            //1、群聊，群里所有人可见
            //2、群聊，只有群主能见

            for (int i = 0; i < toIds.size(); i++) {
                String id = toIds.getString(i);
                UserBean toUser = webSocketService.getUserByID(id);
                sendMessageToUser(fromUser, toUser, type, groupId, data);
            }

        } else {
            //群发

        }


        //群发消息
//        for (MyWebSocket item : webSocketSet) {
//            try {
//                item.sendMessage(message);
//            } catch (IOException e) {
//                e.printStackTrace();
//            }
//        }
    }

    /**
     * 发生错误时调用
     */
    @OnError
    public void onError(Session session, Throwable error) {
        System.out.println("发生错误");
        error.printStackTrace();
    }


    public void sendMessageToUser(UserBean fromUser, UserBean toUser, String type, String groupId, JSONObject data) {
        String sessionId = toUser.getSocketId();
        Session session = getSessionById(sessionId);

        JSONObject message = new JSONObject();
        message.put("type", type);
        message.put("fromUser", fromUser);
        message.put("toUser", toUser);
        message.put("data", data);

        if (session != null) {
            //发送给个人
            sendMessage(session, message.toJSONString());
        } else {
            //对方不在线，存储消息
            UnSendMsgBean unSendMessage = new UnSendMsgBean();
            unSendMessage.setFromId(fromUser.getId());
            unSendMessage.setToId(toUser.getId());
            unSendMessage.setType(type);
            unSendMessage.setData(message.toJSONString());
            if (type.equals("1") || type.equals("2")) {
                //群聊，所有人可见
                unSendMessage.setGroupId(groupId);
            }
            webSocketService.saveUnsendMessage(unSendMessage);
        }

    }


    private Session getSessionById(String sessionId) {
        Session session = null;
        if (sessionId==null){
            return session;
        }

        for (WebSocketControler socket : webSocketSet) {
            if (sessionId.equals(socket.session.getId())) {
                session = socket.session;
                break;
            }
        }

        return session;
    }


    public void sendMessage(String message) {
        try {
            this.session.getBasicRemote().sendText(message);
//            session.getBasicRemote().sendObject(message);
        } catch (Exception e) {
            e.printStackTrace();
        }
        //this.session.getAsyncRemote().sendText(message);
    }

    /**
     * 群发自定义消息
     */
    public static void sendMessage(Session session, String message) {
        try {
            session.getBasicRemote().sendText(message);
//            session.getBasicRemote().sendObject(message);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static synchronized int getOnlineCount() {
        return onlineCount;
    }

    public static synchronized void addOnlineCount() {
        WebSocketControler.onlineCount++;
    }

    public static synchronized void subOnlineCount() {
        WebSocketControler.onlineCount--;
    }
}